package at.favre.lib.armadillo;

import ohos.aafwk.ability.delegation.AbilityDelegatorRegistry;
import ohos.app.Context;
import ohos.data.preferences.Preferences;
import org.junit.Test;

import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.concurrent.atomic.AtomicBoolean;

import static junit.framework.TestCase.*;

/**
 * Instrumented test, which will execute on an Android device.
 *
 * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
 */
public class SecureSharedPreferencesTest extends ASecureSharedPreferencesTest {

    private final Context context = AbilityDelegatorRegistry.getAbilityDelegator().getAppContext();

    protected Armadillo.Builder create(String name, char[] pw) {
        return Armadillo.create(context, name)
                .encryptionFingerprint(context)
                .enableKitKatSupport(isKitKatOrBelow())
                .password(pw);
    }

    @Override
    protected boolean isKitKatOrBelow() {
        return false;
    }

    @Test
    public void quickStartTest() {
        Preferences preferences = Armadillo.create(context, "myPrefs")
                .encryptionFingerprint(context)
                .enableKitKatSupport(isKitKatOrBelow()).build();

        preferences.putString("key1", "string").flush();
        String s = preferences.getString("key1", null);

        assertEquals("string", s);
    }

    @Test
    public void testWithDifferentKeyStrength() {
        preferenceSmokeTest(create("fingerprint", null)
                .encryptionKeyStrength(AuthenticatedEncryption.STRENGTH_VERY_HIGH).build());
    }

    @Test
    public void testSecurePreferenceChangeNotification() {
        ArmadilloSharedPreferences armadilloSharedPreferences = create("fingerprint", null).build();
        AtomicBoolean matched = new AtomicBoolean(false);
        armadilloSharedPreferences.registerOnSecurePreferenceChangeListener(((sharedPreferences, comparison) -> {
            if (comparison.isDerivedKeyEqualTo("key-of-interest")) {
                matched.set(true);
            }
        }));

        armadilloSharedPreferences.putInt("key-of-interest", 3).flushSync();

        assertTrue(matched.get());
    }

    @Test
    public void testSecurePreferenceNotMatching() {
        ArmadilloSharedPreferences armadilloSharedPreferences = create("fingerprint", null).build();
        AtomicBoolean matched = new AtomicBoolean(false);
        armadilloSharedPreferences.registerOnSecurePreferenceChangeListener(((sharedPreferences, comparison) -> {
            if (comparison.isDerivedKeyEqualTo("key-of-interest")) {
                matched.set(true);
            }
        }));

        armadilloSharedPreferences.putInt("another-key", 3).flushSync();

        assertFalse(matched.get());
    }

    @Test
    public void advancedTest() {
        String userId = "1234";
        Preferences preferences = Armadillo.create(context, "myCustomPreferences")
                .password("mySuperSecretPassword".toCharArray()) //use user based password
                .keyStretchingFunction(new PBKDF2KeyStretcher()) //use PBKDF2 as user password kdf
                .secureRandom(new SecureRandom()) //provide your own secure random for salt/iv generation
                .encryptionFingerprint(context, userId.getBytes(StandardCharsets.UTF_8)) //add the user id to fingerprint
                .supportVerifyPassword(true) //enables optional password validation support `.isValidPassword()`
                .enableKitKatSupport(true) //enable optional kitkat support
                .build();

        preferences.putString("key1", "string").flush();
        String s = preferences.getString("key1", null);

        assertEquals("string", s);
    }
}
